home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / gawksrc.cpt / gawk-2.11 source / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-23  |  17.6 KB  |  850 lines

  1. /*
  2.  * io.c - routines for dealing with input and output and records
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27. #ifndef O_RDONLY
  28. #include <fcntl.h>
  29. #endif
  30. #include <signal.h>
  31.  
  32. extern FILE *popen();
  33.  
  34. static void do_file();
  35. static IOBUF *nextfile();
  36. static int get_a_record();
  37. static int iop_close();
  38. static IOBUF *iop_alloc();
  39. static void close_one();
  40. static int close_redir();
  41. static IOBUF *gawk_popen();
  42. static int gawk_pclose();
  43.  
  44. static struct redirect *red_head = NULL;
  45. static int getline_redirect = 0;    /* "getline <file" being executed */
  46.  
  47. extern char *line_buf;
  48. extern int output_is_tty;
  49. extern NODE *ARGC_node;
  50. extern NODE *ARGV_node;
  51. extern NODE **fields_arr;
  52.  
  53. int field_num;
  54.  
  55. static IOBUF *
  56. nextfile()
  57. {
  58.  
  59.     static int i = 1;
  60.     static int files = 0;
  61.     static IOBUF *curfile = NULL;
  62.     char *arg;
  63.     char *cp;
  64.     int fd = -1;
  65.  
  66.     if (curfile != NULL && curfile->cnt != EOF)
  67.         return curfile;
  68.     for (; i < (int) (ARGC_node->lnode->numbr); i++) {
  69.         arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
  70.         if (*arg == '\0')
  71.             continue;
  72.         cp = strchr(arg, '=');
  73.         if (cp != NULL) {
  74.             *cp++ = '\0';
  75.             variable(arg)->var_value = make_string(cp, strlen(cp));
  76.             *--cp = '=';    /* restore original text of ARGV */
  77.         } else {
  78.             files++;
  79.             if (STREQ(arg, "-"))
  80.                 fd = 0;
  81.             else
  82.                 fd = devopen(arg, "r");
  83.             if (fd == -1)
  84.                 fatal("cannot open file `%s' for reading (%s)",
  85.                     arg, strerror(errno));
  86.                 /* NOTREACHED */
  87.             /* This is a kludge.  */
  88.             deref = FILENAME_node->var_value;
  89.             do_deref();
  90.             FILENAME_node->var_value =
  91.                 make_string(arg, strlen(arg));
  92.             FNR_node->var_value->numbr = 0.0;
  93.             i++;
  94.             break;
  95.         }
  96.     }
  97.     if (files == 0) {
  98.         files++;
  99.         /* no args. -- use stdin */
  100.         /* FILENAME is init'ed to "-" */
  101.         /* FNR is init'ed to 0 */
  102.         fd = 0;
  103.     }
  104.     if (fd == -1)
  105.         return NULL;
  106.     return curfile = iop_alloc(fd);
  107. }
  108.  
  109. static IOBUF *
  110. iop_alloc(fd)
  111. int fd;
  112. {
  113.     IOBUF *iop;
  114.  
  115. #ifndef THINK_C
  116.     struct stat stb;
  117.  
  118.     /*
  119.      * System V doesn't have the file system block size in the
  120.      * stat structure. So we have to make some sort of reasonable
  121.      * guess. We use stdio's BUFSIZ, since that is what it was
  122.      * meant for in the first place.
  123.      */
  124. #ifdef BLKSIZE_MISSING
  125. #define    DEFBLKSIZE    BUFSIZ
  126. #else
  127. #define DEFBLKSIZE    (stb.st_blksize ? stb.st_blksize : BUFSIZ)
  128. #endif
  129. #endif
  130.  
  131. #ifdef THINK_C
  132. #define DEFBLKSIZE    BUFSIZ
  133. #endif
  134.     if (fd == -1)
  135.         return NULL;
  136.     emalloc(iop, IOBUF *, sizeof(IOBUF), "nextfile");
  137.     iop->flag = 0;
  138.     if (isatty(fd)) {
  139.         iop->flag |= IOP_IS_TTY;
  140.         iop->size = BUFSIZ;
  141.     } 
  142. #ifndef THINK_C
  143.     else if (fstat(fd, &stb) == -1)
  144.         fatal("can't stat fd %d (%s)", fd, strerror(errno));
  145.     else if (lseek(fd, 0L, 0) == -1)
  146.         iop->size = DEFBLKSIZE;
  147.     else
  148.         iop->size = (stb.st_size < DEFBLKSIZE ?
  149.                 stb.st_size+1 : DEFBLKSIZE);
  150. #else
  151.     iop->size = DEFBLKSIZE;
  152. #endif
  153.     errno = 0;
  154.     iop->fd = fd;
  155.     emalloc(iop->buf, char *, iop->size, "nextfile");
  156.     iop->off = iop->buf;
  157.     iop->cnt = 0;
  158.     iop->secsiz = iop->size < BUFSIZ ? iop->size : BUFSIZ;
  159.     emalloc(iop->secbuf, char *, iop->secsiz, "nextfile");
  160.     return iop;
  161. }
  162.  
  163. void
  164. do_input()
  165. {
  166.     IOBUF *iop;
  167.     extern int exiting;
  168.  
  169.     while ((iop = nextfile()) != NULL) {
  170.         do_file(iop);
  171.         if (exiting)
  172.             break;
  173.     }
  174. }
  175.  
  176. static int
  177. iop_close(iop)
  178. IOBUF *iop;
  179. {
  180.     int ret;
  181.  
  182.     ret = close(iop->fd);
  183.     if (ret == -1)
  184.         warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
  185.     free(iop->buf);
  186.     free(iop->secbuf);
  187.     free((char *)iop);
  188.     return ret == -1 ? 1 : 0;
  189. }
  190.  
  191. /*
  192.  * This reads in a record from the input file
  193.  */
  194. static int
  195. inrec(iop)
  196. IOBUF *iop;
  197. {
  198.     int cnt;
  199.     int retval = 0;
  200.  
  201.     cnt = get_a_record(&line_buf, iop);
  202.     if (cnt == EOF) {
  203.         cnt = 0;
  204.         retval = 1;
  205.     } else {
  206.         if (!getline_redirect) {
  207.             assign_number(&NR_node->var_value,
  208.                 NR_node->var_value->numbr + 1.0);
  209.             assign_number(&FNR_node->var_value,
  210.                 FNR_node->var_value->numbr + 1.0);
  211.         }
  212.     }
  213.     set_record(line_buf, cnt);
  214.  
  215.     return retval;
  216. }
  217.  
  218. static void
  219. do_file(iop)
  220. IOBUF *iop;
  221. {
  222.     /* This is where it spends all its time.  The infamous MAIN LOOP */
  223.     if (inrec(iop) == 0)
  224.         while (interpret(expression_value) && inrec(iop) == 0)
  225.             ;
  226.     (void) iop_close(iop);
  227. }
  228.  
  229. int
  230. get_rs()
  231. {
  232.     register NODE *tmp;
  233.  
  234.     tmp = force_string(RS_node->var_value);
  235.     if (tmp->stlen == 0)
  236.         return 0;
  237.     return *(tmp->stptr);
  238. }
  239.  
  240. /* Redirection for printf and print commands */
  241. struct redirect *
  242. redirect(tree, errflg)
  243. NODE *tree;
  244. int *errflg;
  245. {
  246.     register NODE *tmp;
  247.     register struct redirect *rp;
  248.     register char *str;
  249.     int tflag = 0;
  250.     int outflag = 0;
  251.     char *direction = "to";
  252.     char *mode;
  253.     int fd;
  254.  
  255.     switch (tree->type) {
  256.     case Node_redirect_append:
  257.         tflag = RED_APPEND;
  258.     case Node_redirect_output:
  259.         outflag = (RED_FILE|RED_WRITE);
  260.         tflag |= outflag;
  261.         break;
  262.     case Node_redirect_pipe:
  263.         tflag = (RED_PIPE|RED_WRITE);
  264.         break;
  265.     case Node_redirect_pipein:
  266.         tflag = (RED_PIPE|RED_READ);
  267.         break;
  268.     case Node_redirect_input:
  269.         tflag = (RED_FILE|RED_READ);
  270.         break;
  271.     default:
  272.         fatal ("invalid tree type %d in redirect()", tree->type);
  273.         break;
  274.     }
  275.     tmp = force_string(tree_eval(tree->subnode));
  276.     str = tmp->stptr;
  277.     for (rp = red_head; rp != NULL; rp = rp->next)
  278.         if (STREQ(rp->value, str)
  279.             && ((rp->flag & ~RED_NOBUF) == tflag
  280.             || (outflag
  281.                 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
  282.             break;
  283.     if (rp == NULL) {
  284.         emalloc(rp, struct redirect *, sizeof(struct redirect),
  285.             "redirect");
  286.         emalloc(str, char *, tmp->stlen+1, "redirect");
  287.         memcpy(str, tmp->stptr, tmp->stlen+1);
  288.         rp->value = str;
  289.         rp->flag = tflag;
  290.         rp->offset = 0;
  291.         rp->fp = NULL;
  292.         rp->iop = NULL;
  293.         /* maintain list in most-recently-used first order */
  294.         if (red_head)
  295.             red_head->prev = rp;
  296.         rp->prev = NULL;
  297.         rp->next = red_head;
  298.         red_head = rp;
  299.     }
  300.     while (rp->fp == NULL && rp->iop == NULL) {
  301.         mode = NULL;
  302.         errno = 0;
  303.         switch (tree->type) {
  304.         case Node_redirect_output:
  305.             mode = "w";
  306.             break;
  307.         case Node_redirect_append:
  308.             mode = "a";
  309.             break;
  310.         case Node_redirect_pipe:
  311.             if ((rp->fp = popen(str, "w")) == NULL)
  312.                 fatal("can't open pipe (\"%s\") for output (%s)",
  313.                     str, strerror(errno));
  314.             rp->flag |= RED_NOBUF;
  315.             break;
  316.         case Node_redirect_pipein:
  317.             direction = "from";
  318.             if (gawk_popen(str, rp) == NULL)
  319.                 fatal("can't open pipe (\"%s\") for input (%s)",
  320.                     str, strerror(errno));
  321.             break;
  322.         case Node_redirect_input:
  323.             direction = "from";
  324.             rp->iop = iop_alloc(devopen(str, "r"));
  325.             break;
  326.         default:
  327.             cant_happen();
  328.         }
  329.         if (mode != NULL) {
  330.             fd = devopen(str, mode);
  331.             if (fd != -1) {
  332.                 rp->fp = fdopen(fd, mode);
  333.                 if (isatty(fd))
  334.                     rp->flag |= RED_NOBUF;
  335.             }
  336.         }
  337.         if (rp->fp == NULL && rp->iop == NULL) {
  338.             /* too many files open -- close one and try again */
  339.             if (errno == ENFILE || errno == EMFILE)
  340.                 close_one();
  341.             else {
  342.                 /*
  343.                  * Some other reason for failure.
  344.                  *
  345.                  * On redirection of input from a file,
  346.                  * just return an error, so e.g. getline
  347.                  * can return -1.  For output to file,
  348.                  * complain. The shell will complain on
  349.                  * a bad command to a pipe.
  350.                  */
  351.                 *errflg = 1;
  352.                 if (tree->type == Node_redirect_output
  353.                     || tree->type == Node_redirect_append)
  354.                     fatal("can't redirect %s `%s' (%s)",
  355.                         direction, str, strerror(errno));
  356.                 else
  357.                     return NULL;
  358.             }
  359.         }
  360.     }
  361.     if (rp->offset != 0)    /* this file was previously open */
  362.         if (fseek(rp->fp, rp->offset, 0) == -1)
  363.             fatal("can't seek to %ld on `%s' (%s)",
  364.                 rp->offset, str, strerror(errno));
  365.     free_temp(tmp);
  366.     return rp;
  367. }
  368.  
  369. static void
  370. close_one()
  371. {
  372.     register struct redirect *rp;
  373.     register struct redirect *rplast = NULL;
  374.  
  375.     /* go to end of list first, to pick up least recently used entry */
  376.     for (rp = red_head; rp != NULL; rp = rp->next)
  377.         rplast = rp;
  378.     /* now work back up through the list */
  379.     for (rp = rplast; rp != NULL; rp = rp->prev)
  380.         if (rp->fp && (rp->flag & RED_FILE)) {
  381.             rp->offset = ftell(rp->fp);
  382.             if (fclose(rp->fp))
  383.                 warning("close of \"%s\" failed (%s).",
  384.                     rp->value, strerror(errno));
  385.             rp->fp = NULL;
  386.             break;
  387.         }
  388.     if (rp == NULL)
  389.         /* surely this is the only reason ??? */
  390.         fatal("too many pipes or input files open"); 
  391. }
  392.  
  393. NODE *
  394. do_close(tree)
  395. NODE *tree;
  396. {
  397.     NODE *tmp;
  398.     register struct redirect *rp;
  399.  
  400.     tmp = force_string(tree_eval(tree->subnode));
  401.     for (rp = red_head; rp != NULL; rp = rp->next) {
  402.         if (STREQ(rp->value, tmp->stptr))
  403.             break;
  404.     }
  405.     free_temp(tmp);
  406.     if (rp == NULL) /* no match */
  407.         return tmp_number((AWKNUM) 0.0);
  408.     fflush(stdout);    /* synchronize regular output */
  409.     return tmp_number((AWKNUM)close_redir(rp));
  410. }
  411.  
  412. static int
  413. close_redir(rp)
  414. register struct redirect *rp;
  415. {
  416.     int status = 0;
  417.  
  418.     if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE))
  419.         status = pclose(rp->fp);
  420.     else if (rp->fp)
  421.         status = fclose(rp->fp);
  422.     else if (rp->iop) {
  423.         if (rp->flag & RED_PIPE)
  424.             status = gawk_pclose(rp);
  425.         else
  426.             status = iop_close(rp->iop);
  427.  
  428.     }
  429.     /* SVR4 awk checks and warns about status of close */
  430.     if (status)
  431.         warning("failure status (%d) on %s close of \"%s\" (%s).",
  432.             status,
  433.             (rp->flag & RED_PIPE) ? "pipe" :
  434.             "file", rp->value, strerror(errno));
  435.     if (rp->next)
  436.         rp->next->prev = rp->prev;
  437.     if (rp->prev)
  438.         rp->prev->next = rp->next;
  439.     else
  440.         red_head = rp->next;
  441.     free(rp->value);
  442.     free((char *)rp);
  443.     return status;
  444. }
  445.  
  446. int
  447. flush_io ()
  448. {
  449.     register struct redirect *rp;
  450.     int status = 0;
  451.  
  452.     errno = 0;
  453.     if (fflush(stdout)) {
  454.         warning("error writing standard output (%s).", strerror(errno));
  455.         status++;
  456.     }
  457.     errno = 0;
  458.     if (fflush(stderr)) {
  459.         warning("error writing standard error (%s).", strerror(errno));
  460.         status++;
  461.     }
  462.     for (rp = red_head; rp != NULL; rp = rp->next)
  463.         /* flush both files and pipes, what the heck */
  464.         if ((rp->flag & RED_WRITE) && rp->fp != NULL)
  465.             if (fflush(rp->fp)) {
  466.                 warning("%s flush of \"%s\" failed (%s).",
  467.                     (rp->flag  & RED_PIPE) ? "pipe" :
  468.                     "file", rp->value, strerror(errno));
  469.                 status++;
  470.             }
  471.     return status;
  472. }
  473.  
  474. int
  475. close_io ()
  476. {
  477.     register struct redirect *rp;
  478.     int status = 0;
  479.  
  480.     for (rp = red_head; rp != NULL; rp = rp->next)
  481.         if (close_redir(rp))
  482.             status++;
  483.     return status;
  484. }
  485.  
  486. /* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
  487. int
  488. devopen (name, mode)
  489. char *name, *mode;
  490. {
  491.     int openfd = -1;
  492.     FILE *fdopen ();
  493.     char *cp;
  494.     int flag = 0;
  495.  
  496.     switch(mode[0]) {
  497.     case 'r':
  498.         flag = O_RDONLY;
  499.         break;
  500.  
  501.     case 'w':
  502.         flag = O_WRONLY|O_CREAT|O_TRUNC;
  503.         break;
  504.  
  505.     case 'a':
  506.         flag = O_WRONLY|O_APPEND|O_CREAT;
  507.         break;
  508.     default:
  509.         cant_happen();
  510.     }
  511.  
  512. #if defined(STRICT) || defined(NO_DEV_FD)
  513.     return (open (name, flag, 0666));
  514. #else
  515.     if (strict)
  516. #ifndef THINK_C
  517.         return (open (name, flag, 0666));
  518. #else
  519.         return (open (name, flag));
  520. #endif
  521. #endif
  522.     if (!STREQN (name, "/dev/", 5))
  523. #ifndef THINK_C
  524.         return (open (name, flag, 0666));
  525. #else
  526.         return(open (name, flag));
  527. #endif
  528.     else
  529.         cp = name + 5;
  530.         
  531.     /* XXX - first three tests ignore mode */
  532.     if (STREQ(cp, "stdin"))
  533.         return (0);
  534.     else if (STREQ(cp, "stdout"))
  535.         return (1);
  536.     else if (STREQ(cp, "stderr"))
  537.         return (2);
  538.     else if (STREQN(cp, "fd/", 3)) {
  539.         cp += 3;
  540.         if (sscanf (cp, "%d", & openfd) == 1 && openfd >= 0)
  541.             /* got something */
  542.             return openfd;
  543.         else
  544.             return -1;
  545.     } else
  546. #ifndef THINK_C
  547.         return (open (name, flag, 0666));
  548. #else
  549.         return (open (name, flag));
  550. #endif
  551.  
  552. }
  553.  
  554. #ifndef MSDOS
  555. static IOBUF *
  556. gawk_popen(cmd, rp)
  557. char *cmd;
  558. struct redirect *rp;
  559. {
  560.     int p[2];
  561.     register int pid;
  562.  
  563.     rp->pid = -1;
  564.     rp->iop = NULL;
  565.     if (pipe(p) < 0)
  566.         return NULL;
  567.     if ((pid = fork()) == 0) {
  568.         close(p[0]);
  569.         dup2(p[1], 1);
  570.         close(p[1]);
  571.         execl("/bin/sh", "sh", "-c", cmd, 0);
  572.         _exit(127);
  573.     }
  574.     if (pid == -1)
  575.         return NULL;
  576.     rp->pid = pid;
  577.     close(p[1]);
  578.     return (rp->iop = iop_alloc(p[0]));
  579. }
  580.  
  581. static int
  582. gawk_pclose(rp)
  583. struct redirect *rp;
  584. {
  585.     SIGTYPE (*hstat)(), (*istat)(), (*qstat)();
  586.     int pid;
  587.     int status;
  588.     struct redirect *redp;
  589.  
  590.     iop_close(rp->iop);
  591.     if (rp->pid == -1)
  592.         return rp->status;
  593.     istat = signal(SIGINT, SIG_IGN);
  594. #ifndef THINK_C
  595.     hstat = signal(SIGHUP, SIG_IGN);
  596.     qstat = signal(SIGQUIT, SIG_IGN);
  597. #else
  598.     hstat = signal(SIGABRT, SIG_IGN);
  599.     qstat = signal(SIGTERM, SIG_IGN);
  600. #endif
  601.     for (;;) {
  602.         pid = wait(&status);
  603. #ifndef THINK_C
  604.         if (pid == -1 && errno == ECHILD)
  605. #else
  606.         if (pid == -1)
  607. #endif
  608.             break;
  609.         else if (pid == rp->pid) {
  610.             rp->pid = -1;
  611.             rp->status = status;
  612.             break;
  613.         } else {
  614.             for (redp = red_head; redp != NULL; redp = redp->next)
  615.                 if (pid == redp->pid) {
  616.                     redp->pid = -1;
  617.                     redp->status = status;
  618.                     break;
  619.                 }
  620.         }
  621.     }
  622.     signal(SIGINT, istat);
  623. #ifndef THINK_C
  624.     signal(SIGHUP, hstat);
  625.     signal(SIGQUIT, qstat);
  626. #else
  627.     signal(SIGABRT, hstat);
  628.     signal(SIGTERM, qstat);
  629. #endif
  630.     return(rp->status);
  631. }
  632. #else
  633. static
  634. struct {
  635.     char *command;
  636.     char *name;
  637. } pipes[_NFILE];
  638.  
  639. static IOBUF *
  640. gawk_popen(cmd, rp)
  641. char *cmd;
  642. struct redirect *rp;
  643. {
  644.     extern char *strdup(const char *);
  645.     int current;
  646.     char *name;
  647.     static char cmdbuf[256];
  648.  
  649.     /* get a name to use.  */
  650.     if ((name = tempnam(".", "pip")) == NULL)
  651.         return NULL;
  652.     sprintf(cmdbuf,"%s > %s", cmd, name);
  653.     system(cmdbuf);
  654.     if ((current = open(name,O_RDONLY)) == -1)
  655.         return NULL;
  656.     pipes[current].name = name;
  657.     pipes[current].command = strdup(cmd);
  658.     return (rp->iop = iop_alloc(current));
  659. }
  660.  
  661. static int
  662. gawk_pclose(rp)
  663. struct redirect *rp;
  664. {
  665.     int cur = rp->iop->fd;
  666.     int rval;
  667.  
  668.     rval = iop_close(rp->iop);
  669.  
  670.     /* check for an open file  */
  671.     if (pipes[cur].name == NULL)
  672.         return -1;
  673.     unlink(pipes[cur].name);
  674.     free(pipes[cur].name);
  675.     pipes[cur].name = NULL;
  676.     free(pipes[cur].command);
  677.     return rval;
  678. }
  679. #endif
  680.  
  681. #define    DO_END_OF_BUF    len = bp - iop->off;\
  682.             used = last - start;\
  683.             while (len + used > iop->secsiz) {\
  684.                 iop->secsiz *= 2;\
  685.                 erealloc(iop->secbuf,char *,iop->secsiz,"get");\
  686.             }\
  687.             last = iop->secbuf + used;\
  688.             start = iop->secbuf;\
  689.             memcpy(last, iop->off, len);\
  690.             last += len;\
  691.             iop->cnt = read(iop->fd, iop->buf, iop->size);\
  692.             if (iop->cnt < 0)\
  693.                 return iop->cnt;\
  694.             end_data = iop->buf + iop->cnt;\
  695.             iop->off = bp = iop->buf;
  696.  
  697. #define    DO_END_OF_DATA    iop->cnt = read(iop->fd, end_data, end_buf - end_data);\
  698.             if (iop->cnt < 0)\
  699.                 return iop->cnt;\
  700.             end_data += iop->cnt;\
  701.             if (iop->cnt == 0)\
  702.                 break;\
  703.             iop->cnt = end_data - iop->buf;
  704.  
  705. static int
  706. get_a_record(res, iop)
  707. char **res;
  708. IOBUF *iop;
  709. {
  710.     register char *end_data;
  711.     register char *end_buf;
  712.     char *start;
  713.     register char *bp;
  714.     register char *last;
  715.     int len, used;
  716.     register char rs = get_rs();
  717.  
  718.     if (iop->cnt < 0)
  719.         return iop->cnt;
  720.     if ((iop->flag & IOP_IS_TTY) && output_is_tty)
  721.         fflush(stdout);
  722.     end_data = iop->buf + iop->cnt;
  723.     if (iop->off >= end_data) {
  724.         iop->cnt = read(iop->fd, iop->buf, iop->size);
  725.         if (iop->cnt <= 0)
  726.             return iop->cnt = EOF;
  727.         end_data = iop->buf + iop->cnt;
  728.         iop->off = iop->buf;
  729.     }
  730.     last = start = bp = iop->off;
  731.     end_buf = iop->buf + iop->size;
  732.     if (rs == 0) {
  733.         while (!(*bp == '\n' && bp != iop->buf && bp[-1] == '\n')) {
  734.             if (++bp == end_buf) {
  735.                 DO_END_OF_BUF
  736.             }
  737.             if (bp == end_data) {
  738.                 DO_END_OF_DATA
  739.             }
  740.         }
  741.         if (*bp == '\n' && bp != iop->off && bp[-1] == '\n') {
  742.             int tmp = 0;
  743.  
  744.             /* allow for more than two newlines */
  745.             while (*bp == '\n') {
  746.                 tmp++;
  747.                 if (++bp == end_buf) {
  748.                     DO_END_OF_BUF
  749.                 }
  750.                 if (bp == end_data) {
  751.                     DO_END_OF_DATA
  752.                 }
  753.             }
  754.             iop->off = bp;
  755.             bp -= 1 + tmp;
  756.         } else if (bp != iop->buf && bp[-1] != '\n') {
  757.             warning("record not terminated");
  758.             iop->off = bp + 2;
  759.         } else {
  760.             bp--;
  761.             iop->off = bp + 2;
  762.         }
  763.     } else {
  764.         while (*bp++ != rs) {
  765.             if (bp == end_buf) {
  766.                 DO_END_OF_BUF
  767.             }
  768.             if (bp == end_data) {
  769.                 DO_END_OF_DATA
  770.             }
  771.         }
  772.         if (*--bp != rs) {
  773.             warning("record not terminated");
  774.             bp++;
  775.         }
  776.         iop->off = bp + 1;
  777.     }
  778.     if (start == iop->secbuf) {
  779.         len = bp - iop->buf;
  780.         if (len > 0) {
  781.             used = last - start;
  782.             while (len + used > iop->secsiz) {
  783.                 iop->secsiz *= 2;
  784.                 erealloc(iop->secbuf,char *,iop->secsiz,"get2");
  785.             }
  786.             last = iop->secbuf + used;
  787.             start = iop->secbuf;
  788.             memcpy(last, iop->buf, len);
  789.             last += len;
  790.         }
  791.     } else
  792.         last = bp;
  793.     *last = '\0';
  794.     *res = start;
  795.     return last - start;
  796. }
  797.  
  798. NODE *
  799. do_getline(tree)
  800. NODE *tree;
  801. {
  802.     struct redirect *rp;
  803.     IOBUF *iop;
  804.     int cnt;
  805.     NODE **lhs;
  806.     int redir_error = 0;
  807.  
  808.     if (tree->rnode == NULL) {     /* no redirection */
  809.         iop = nextfile();
  810.         if (iop == NULL)        /* end of input */
  811.             return tmp_number((AWKNUM) 0.0);
  812.     } else {
  813.         rp = redirect(tree->rnode, &redir_error);
  814.         if (rp == NULL && redir_error)    /* failed redirect */
  815.             return tmp_number((AWKNUM) -1.0);
  816.         iop = rp->iop;
  817.         getline_redirect++;
  818.     }
  819.     if (tree->lnode == NULL) {    /* no optional var. -- read in $0 */
  820.         if (inrec(iop) != 0) {
  821.             getline_redirect = 0;
  822.             return tmp_number((AWKNUM) 0.0);
  823.         }
  824.     } else {            /* read in a named variable */
  825.         char *s = NULL;
  826.  
  827.         lhs = get_lhs(tree->lnode, 1);
  828.         cnt = get_a_record(&s, iop);
  829.         if (!getline_redirect) {
  830.             assign_number(&NR_node->var_value,
  831.                 NR_node->var_value->numbr + 1.0);
  832.             assign_number(&FNR_node->var_value,
  833.                 FNR_node->var_value->numbr + 1.0);
  834.         }
  835.         if (cnt == EOF) {
  836.             getline_redirect = 0;
  837.             free(s);
  838.             return tmp_number((AWKNUM) 0.0);
  839.         }
  840.         *lhs = make_string(s, strlen(s));
  841.         do_deref();
  842.         /* we may have to regenerate $0 here! */
  843.         if (field_num == 0)
  844.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  845.         field_num = -1;
  846.     }
  847.     getline_redirect = 0;
  848.     return tmp_number((AWKNUM) 1.0);
  849. }
  850.